<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<style>
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote {
    margin: 0;
    padding: 0;
}
body {
    font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
    font-size: 13px;
    line-height: 18px;
    color: #737373;
    background-color: white;
    margin: 10px 13px 10px 13px;
}
table {
	margin: 10px 0 15px 0;
	border-collapse: collapse;
}
td,th {	
	border: 1px solid #ddd;
	padding: 3px 10px;
}
th {
	padding: 5px 10px;	
}

a {
    color: #0069d6;
}
a:hover {
    color: #0050a3;
    text-decoration: none;
}
a img {
    border: none;
}
p {
    margin-bottom: 9px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    color: #404040;
    line-height: 36px;
}
h1 {
    margin-bottom: 18px;
    font-size: 30px;
}
h2 {
    font-size: 24px;
}
h3 {
    font-size: 18px;
}
h4 {
    font-size: 16px;
}
h5 {
    font-size: 14px;
}
h6 {
    font-size: 13px;
}
hr {
    margin: 0 0 19px;
    border: 0;
    border-bottom: 1px solid #ccc;
}
blockquote {
    padding: 13px 13px 21px 15px;
    margin-bottom: 18px;
    font-family:georgia,serif;
    font-style: italic;
}
blockquote:before {
    content:"\201C";
    font-size:40px;
    margin-left:-10px;
    font-family:georgia,serif;
    color:#eee;
}
blockquote p {
    font-size: 14px;
    font-weight: 300;
    line-height: 18px;
    margin-bottom: 0;
    font-style: italic;
}
code, pre {
    font-family: Monaco, Andale Mono, Courier New, monospace;
}
code {
    background-color: #fee9cc;
    color: rgba(0, 0, 0, 0.75);
    padding: 1px 3px;
    font-size: 12px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
}
pre {
    display: block;
    padding: 14px;
    margin: 0 0 18px;
    line-height: 16px;
    font-size: 11px;
    border: 1px solid #d9d9d9;
    white-space: pre-wrap;
    word-wrap: break-word;
}
pre code {
    background-color: #fff;
    color:#737373;
    font-size: 11px;
    padding: 0;
}
sup {
    font-size: 0.83em;
    vertical-align: super;
    line-height: 0;
}
* {
	-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
    body {
        width: 854px;
        margin:10px auto;
    }
}
@media print {
	body,code,pre code,h1,h2,h3,h4,h5,h6 {
		color: black;
	}
	table, pre {
		page-break-inside: avoid;
	}
}
</style>
<title>React-Native入门指南</title>

</head>
<body>
<h1>React-Native入门指南</h1>

<h2>第四篇React-Native布局实战(二)</h2>

<pre><code>在不断深入的过程中，发现React-Native布局和样式的坑还有很多，他没有像浏览器那样灵活和有规律可循，其中的规律需要我自己踩坑的时候发现。比如：不存在zIndex,后面的元素覆盖前面的元素；内层元素覆盖外层元素等等,borderRadius的设置，需要考虑到内层元素的位置等等。
</code></pre>

<h3>一、实战的内容</h3>

<pre><code>这里选用携程的App首页作为栗子，随不是严格的9宫格(比9宫格稍微难点...)，但是可以很好的让我们练习flexbox.最后需要完成的结果如下：
</code></pre>

<p><img src="pic/4_0_1.png" alt="'首页'" /></p>

<h3>二、分解内容</h3>

<pre><code>整个页面我们可以分为几个部分，大致如下：
</code></pre>

<ul>
<li>头部</li>
<li>图片轮播</li>
<li>9宫格</li>
<li>底部活动</li>
</ul>


<h3>三、头部导航栏</h3>

<pre><code>因为，组件还没有讲，这里只是做一个简单的介绍。在React-Native中实现头部导航栏很简单，只要使用NavigatorIOS组件即可。现在开工。

1、我们在index.ios.js中添加如下代码；同时创建文件夹pagaes和pages下创建Index.js
var React = require('react-native');
var Index = require('./pages/Index');

var {
    NavigatorIOS,
    AppRegistry,
    StyleSheet,
} = React;

var NV = React.createClass({
    render: function(){
        return(
            &lt;NavigatorIOS
                style={styles.container}
                initialRoute={{
                    title: '首页',
                    component: Index,
                }}
            /&gt;
        );
    }
});

var styles = StyleSheet.create({
    container: {
        flex: 1,
    }
});


AppRegistry.registerComponent('HelloWorld', () =&gt; NV);

分析代码：
 （1）require：引入外部模块，就像，引入我们自己创建的/pages/Index.js一样。
 （2）引入定义NavigatorIOS、AppRegistry、StyleSheet组件和类。
 （3）在render中调用NavigatorIOS组件，initialRoute是初始化路由，title是当前页面的头部标题；component是当前路由下显示的组件；
 （4）注意：这里NavigatorIOS的style需要设置大小，比如这里设置是flex：1，否则就不能显示内容主体；
 （5）最后我们需要注册当前应用：AppRegistry.registerComponent('HelloWorld', () =&gt; NV);

 2、创建Index.js文件，文件的内容如下, module.exports就暴露了Index模块。
</code></pre>

<p><img src="pic/4_0_3.png" alt="'Index'" />
     效果如下图：
<img src="pic/4_0_2.png" alt="'头部'" /></p>

<h3>四、图片轮播</h3>

<pre><code>这里图片轮播使用的是第三方组件react-native-swiper,当然React-Native是支持transform可以直接实现一套。我们启动npm命令行，在项目的根目录使用如下命令安装模块。

$ npm install react-native-swiper --save
$ npm i react-timer-mixin --save
</code></pre>

<p>(2)需要关闭React packager命令行和模拟器，在xcode中重启项目</p>

<pre><code>安装完成后，我们需要完成轮播功能。因为可以到github看看swiper暴露的接口和参数。github地址是：https://github.com/leecade/react-native-swiper

（1）引入swiper,前面也提到了require.
var Swiper = require('react-native-swiper');

（2）使用swiper,将轮播图封装成单独的组件
var sliderImgs = [
    'http://images3.c-ctrip.com/SBU/apph5/201505/16/app_home_ad16_640_128.png',
    'http://images3.c-ctrip.com/rk/apph5/C1/201505/app_home_ad49_640_128.png',
    'http://images3.c-ctrip.com/rk/apph5/D1/201506/app_home_ad05_640_128.jpg'
];
var Slider = React.createClass({
    render: function(){
    return (
      &lt;Swiper style={styles.wrapper} showsButtons={false} autoplay={true} height={150} showsPagination={false}&gt;
        &lt;Image style={[styles.slide,]} source={{uri: sliderImgs[0]}}&gt;&lt;/Image&gt;
        &lt;Image style={[styles.slide,]} source={{uri: sliderImgs[1]}}&gt;&lt;/Image&gt;
        &lt;Image style={[styles.slide,]} source={{uri: sliderImgs[2]}}&gt;&lt;/Image&gt;
      &lt;/Swiper&gt;
    );
  }
});
(3)这样我们可以直接在render的时候直接用：&lt;Slider/&gt;
</code></pre>

<h3>五、完成第一个9宫格布局，后面复制拷贝</h3>

<pre><code>其实4个九宫格都是一样，这个其实可以封装成组件，这里采用拷贝的形式，开发一个，其他3个就ok的，不会偷懒的工程师，不是好工程师［偷笑］。分析下布局：
（1）其实首先是3个列在一行的布局，那么外层组件是需要flexDirection: 'row'，各占据宽度的1/3,即各自flex:1；
（2）每个列内又分两行， 需要每个行都是flex:1,各占据高度的一半；
（3）第一列是文字图片组合，其余都是文字组合；
（4）所有行内元素都是水平、垂直居中；
（5）这里使用了个TouchableHighlight组件，是为了出发onPress事件，类似于click或者touch事件。

        &lt;View style={[styles.sbu_red, styles.sbu_view]}&gt;
        &lt;TouchableHighlight underlayColor={'#FA6778'} style={{flex:1}}&gt;
            &lt;View style={[styles.sbu_flex, styles.sbu_borderRight]}&gt;
                &lt;View style={[styles.sub_con_flex, styles.sub_text]}&gt;
                    &lt;Text style={[styles.font16]}&gt;酒店&lt;/Text&gt;
                &lt;/View&gt;
                &lt;View style={[styles.sub_con_flex]}&gt;
                    &lt;Image style={[styles.sbu_icon_img]} source={{uri:BUIcon[0]}}&gt;&lt;/Image&gt;
                &lt;/View&gt;
            &lt;/View&gt;
        &lt;/TouchableHighlight&gt;
        &lt;View style={[styles.sbu_flex, styles.sbu_borderRight]}&gt;
            &lt;View style={[styles.sub_con_flex, styles.sub_text, styles.sbu_borderBottom]}&gt;
                &lt;Text style={[styles.font16]}&gt;海外&lt;/Text&gt;
            &lt;/View&gt;
            &lt;View style={[styles.sub_con_flex, styles.sub_text]}&gt;
                &lt;Text style={[styles.font16]}&gt;周边&lt;/Text&gt;
            &lt;/View&gt;
        &lt;/View&gt;
        &lt;View style={[styles.sbu_flex]}&gt;
            &lt;View style={[styles.sub_con_flex, styles.sub_text, styles.sbu_borderBottom]}&gt;
                &lt;Text style={[styles.font16]}&gt;团购.特惠&lt;/Text&gt;
            &lt;/View&gt;
            &lt;View style={[styles.sub_con_flex, styles.sub_text]}&gt;
                &lt;Text style={[styles.font16]}&gt;客栈.公寓&lt;/Text&gt;
            &lt;/View&gt;
        &lt;/View&gt;
    &lt;/View&gt; 
</code></pre>

<h3>六、样式类</h3>

<pre><code>说完了布局的原理，这里需要贴上样式仅供参考：
var styles = StyleSheet.create({
//container
container:{
    backgroundColor:'#F2F2F2',
    flex:1,
},
//slider
wrapper: {
    height:80,
},
slide: {
    height:80,
    resizeMode: Image.resizeMode.contain,
},
//sbu
sbu_view:{
    height:84,
    marginLeft: 5,
    marginRight:5,
    borderWidth:1,
    borderRadius:5,
    marginBottom:10,
    flexDirection:'row',
},
sbu_red:{
    backgroundColor: '#FA6778',
    borderColor:'#FA6778',
    marginTop:-70,
},

sbu_blue:{
    backgroundColor: '#3D98FF',
    borderColor:'#3D98FF',
},

sbu_green:{
    backgroundColor: '#5EBE00',
    borderColor:'#5EBE00',
},

sbu_yellow:{
    backgroundColor: '#FC9720',
    borderColor:'#FC9720',
},
sbu_flex:{
    flex:1,
},
sbu_borderRight:{
    borderColor:'#fff',
    borderRightWidth: 0.5,
},
sbu_icon_img:{
    height:40,
    width:40,
    resizeMode:Image.resizeMode.contain,
},
sub_con_flex:{
    flex:1,
    justifyContent: 'center',
    alignItems: 'center',
},
sub_text:{
    justifyContent:'center',
},
font16:{
    fontSize:17,
    color:'#FFF',
    fontWeight:'900',
},
sbu_borderBottom:{
    borderBottomWidth:0.5,
    borderBottomColor:'#fff',
},
img_view:{
    height:62,
    marginLeft:5,
    marginRight:5,
    flexDirection: 'row',
    marginBottom:20,
    backgroundColor:'#fff',
},
img_flex:{
    flex:1,
    borderWidth:1,
    borderColor:'#ccc',
},
img_wh: {
    height:59,
    borderRightWidth:0,
    resizeMode:Image.resizeMode.contain,
}
});

着重说下resizeMode:Image.resizeMode.contain。在React-Native中图片的大小是不会根据给定一个宽度或者高度而自适应大小的，因此我们需要让图片根据宽度或者高度来自适应，那么可以使用resizeMode:Image.resizeMode.contain。facebook提示错误信息的样式表中也没有提及，文档中也没有提及。所以后续还有不少的坑需要大家去一起探索。
</code></pre>

<h3>七、Index.js整个代码，仅供参考</h3>

<pre><code>实例代码中会涉及ScrollView组件，主要是为了适应小屏的机器，可以滚动视图。
</code></pre>

<p><a href="https://github.com/vczero/react-native-lession/tree/master/code/%E7%AC%AC4%E7%AF%87%E5%B8%83%E5%B1%80%E5%AE%9E%E6%88%98%EF%BC%88%E4%BA%8C%EF%BC%89%E4%BB%A3%E7%A0%81">代码链接：github</a></p>
</body>
</html>